﻿//-----------------------------------------------------------------------------
// Torque X Game Engine + mod by Tyler Reid
// Copyright ? GarageGames.com, Inc.
//-----------------------------------------------------------------------------


///-----------------------------------------------------------------------------
///
/// This works the exact same as a regular GUIBitmap, except that when you create your style you have to have
/// values for NumCells and DisplayedCell. NumCells is just a vector storing how many horzontal and how many
/// vertical cells. DisplayedCell is simply the x,y coordinate for which cell you want to display.
/// 
///-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using GarageGames.Torque.Core;
using GarageGames.Torque.GFX;
using GarageGames.Torque.MathUtil;
using GarageGames.Torque.Materials;
using GarageGames.Torque.Util;



namespace GarageGames.Torque.GUI
{
    /// <summary>
    /// Draws an image to the GUICanvas.
    /// </summary>
    public class GUICellBitmap : GUIBitmap
    {

        #region Public properties, operators, constants, and enums

        /// <summary>
        /// The cell that is to be displayed
        /// </summary>
        public Vector2 DisplayedCell
        {
            get { return _displayedCell; }
            set { _displayedCell = value; }
        }

        public Vector2 NumCells
        {
            get { return _numCells; }
            set { _numCells = value; }
        }

        /// <summary>
        /// The image file to render to the screen.
        /// </summary>
        public string Bitmap
        {
            get { return _bitmapName; }
            set
            {
                _bitmapName = value;
                if (NumCells == Vector2.Zero)
                {
                    Assert.Fatal(false, "Must set NumCells before setting a bitmap");
                }
                else
                {
                    if (_bitmapName != String.Empty)
                    {
                        if (_material != null)
                            _material.Dispose();

                        _material = new Materials.SimpleMaterial();
                        _material.TextureFilename = _bitmapName;
                        _material.IsTranslucent = true;
                        _material.IsColorBlended = true;

                        // rdbnote: the render material should really handle this for me
                        Resource<Texture> res = ResourceManager.Instance.LoadTexture(_material.TextureFilename);
                        Texture2D texture = (Texture2D)res.Instance;

                        _material.SetTexture(res.Instance);

                        _bitmapSize = new Vector2(texture.Width, texture.Height);

                        if (_style != null && _style.SizeToBitmap)
                            Size = new Vector2(_bitmapSize.X / NumCells.X, _bitmapSize.X / NumCells.Y);

                        // invalidate the temp. resource
                        res.Invalidate();
                    }
                    else
                    {
                        if (_material != null)
                            _material.Dispose();
                        _material = null;
                    }
                }
            }
        }

        public override void CopyTo(TorqueObject obj)
        {
            base.CopyTo(obj);

            GUICellBitmap obj2 = (GUICellBitmap)obj;

            obj2.DisplayedCell = DisplayedCell;
            obj2.NumCells = NumCells;
            obj2.Bitmap = Bitmap;
        }

        #endregion


        #region Public methods

        public override void OnRender(Vector2 offset, RectangleF updateRect)
        {
#if DEBUG
            Profiler.Instance.StartBlock("GUICellBitmap.OnRender");
#endif

            // clear bitmap modulation
            DrawUtil.ClearBitmapModulation();

            RectangleF ctrlRect = new RectangleF(offset, _bounds.Extent);

            // fill in, if appropriate
            if (_style.IsOpaque)
                DrawUtil.RectFill(ctrlRect, _style.FillColor[CustomColor.ColorBase]);

            // set the opacity of the material
            _material.Opacity = _opacity;

            if (_material != null)
            {
                if (_material.Texture.IsNull)
                    Bitmap = _bitmapName;

                // check for NumCells value
                if (NumCells == null || NumCells.X == 0 || NumCells.Y == 0)
                {
                    Assert.Fatal(false, "GUICellBitmap NumCells is null or has invalid range. Must be an integer above 0.");
                    return;
                }
                // check for out of bounds.
                if (DisplayedCell.X > NumCells.X - 1 || DisplayedCell.Y > NumCells.Y - 1)
                {
                    Assert.Fatal(false, "GUICellBitmap DisplayedCell is out of range of NumCells");
                    return;
                }

                // draw the bitmap
                srcRegion.X = DisplayedCell.X * (_bitmapSize.X / NumCells.X);
                srcRegion.Y = DisplayedCell.Y * (_bitmapSize.Y / NumCells.Y);
                srcRegion.Width = _bitmapSize.X / NumCells.X;
                srcRegion.Height = _bitmapSize.Y / NumCells.Y;

                dstRegion.X = offset.X;
                dstRegion.Y = offset.Y;
                dstRegion.Width = _bounds.Extent.X;
                dstRegion.Height = _bounds.Extent.Y;
                DrawUtil.BitmapStretchSR(_material, dstRegion, srcRegion, BitmapFlip.None);

            }

            // draw a border, if appropriate
            if (_style.HasBorder)
                DrawUtil.Rect(ctrlRect, _style.BorderColor[CustomColor.ColorBase]);

#if DEBUG
            Profiler.Instance.EndBlock("GUICellBitmap.OnRender");
#endif

            // render the child controls
            _RenderChildControls(offset, updateRect);
        }
        #endregion


        #region Private, protected, internal methods

        protected override bool _OnNewStyle(GUIStyle style)
        {
            _style = (style as GUIBitmapStyle);

            Assert.Fatal(_style != null, "GUIBitmap._OnNewStyle - Control was assigned an invalid style!");

            if (_style == null || !base._OnNewStyle(style))
                return false;

            if (_style.SizeToBitmap && _material != null)
                Size = new Vector2(_bitmapSize.X, _bitmapSize.Y);

            return true;
        }

        public override void Dispose()
        {
            _IsDisposed = true;
            _bitmapName = null;
            _material = null;
            _style = null;
            base.Dispose();
        }

        #endregion


        #region Private, protected, internal fields

        string _bitmapName = String.Empty;
        Materials.SimpleMaterial _material = null;

        float _opacity = 1.0f;

        private Vector2 _numCells;
        private Vector2 _displayedCell;

        RectangleF srcRegion = new RectangleF();
        RectangleF dstRegion = new RectangleF();

        Vector2 _bitmapSize;

        GUIBitmapStyle _style = null;

        #endregion
    }
}